﻿/********************************************************
*
* 文件名:  qtlottiewidget.h
* 版权:    Artin Co. Ltd. Copyright 2024 All Rights Reserved.
* 描述:    基于rlottie的qt用lottie动画播放视窗
*
* 修改人:  Lon
* 修改内容:
* 版本:     1.0
* 修改时间: 2024-11-14
*
********************************************************/
#ifndef QTLOTTIEWIDGET_H
#define QTLOTTIEWIDGET_H

#include <QWidget>
#include <QMutex>
#include <rlottie.h>
#include <QTimeLine>
//Lottie动画转换gif图像
extern bool lottie2gif(const QString& lottieFile, const QString& gifFile,
    const QColor& bgColor = Qt::white, const QSize& size = QSize(),
    bool useTransparentBit = false);
//Lottie动画播放控件
class QtLottieWidget : public QWidget
{
    Q_OBJECT
public:
    //循环播放模式
    enum RepeatMode {
        RM_Restart, //正常从头播放
        RM_Reverse  //倒转顺序播放
    };
    explicit QtLottieWidget(QWidget *parent = nullptr);
    ~QtLottieWidget();
    //从文件加载josn数据
    bool loadFromFile(
        const QString &filePath, bool loadResource = true);
    //直接加载json数据
    bool loadFromData(const QString &jsonData,
        const QString &key = QString(),
        const QString &resourcePath = QString());
    //是否加载
    bool isLoaded();
    //设置当前播放时间(单位：秒)
    void setCurTime(float second);
    //获得当前播放时间(单位：秒)
    float getCurTime();
    //设置当前帧数
    void setCurFrame(int frame);
    //开始播放
    bool play();
    //从标签播放
    bool play(const QString &marker);
    bool play(const QString &startMarker,
        const QString endMarker);
    //继续播放
    bool resume();
    //暂停播放
    bool pause();
    //停止播放
    bool stop();
    //设置循环次数(默认1)
    void setLoopCount(int count);
    //设置播放速率(默认1.0)
    void setSpeed(float speed);
    //设置循环模式
    void setRepeatMode(RepeatMode mode);
    //获得fps
    double getFrameRate();
    //获得动画总帧数
    qint64 getAllFrame();
    //获得动画总时长
    double getAllTime();
    //获得lottie原始默认尺寸
    QSize getDefaultSize();
    //获得播放器对像
    rlottie::Animation* player();
    //获得当前帧图像
    QImage getImage();
    //获得默认尺寸图像
    QImage getDefaultImage();
    //关闭所有加载
    void unload();
    //获得动画标记列表
    QStringList getAllMarkers();
    //导出GIF图像
    bool exportGif(
        const QString& gifFile, const QColor& bgColor = Qt::white,
        const QSize& size = QSize(), bool useTransparentBit = false);
Q_SIGNALS:
    void sigFrameChange(int frame, int ms = 0);
    void sigFinished();
private:
    typedef std::tuple<size_t, size_t> MarkerFrame;
    MarkerFrame findFrameAtMarker(const std::string &markerName);
    void resizeEvent(QResizeEvent* e) override;
    void paintEvent(QPaintEvent* e) override;
    void init();
    void render(int frame);
private:
    std::unique_ptr<rlottie::Animation> m_player{};
    std::atomic_int         m_loopCount{1};
    std::atomic_int         m_curCount{1};
    std::atomic<RepeatMode> m_repeatMode{RM_Restart};
    std::atomic<float>      m_speed{1.0f};
    std::atomic<float>      m_pos{0.0f};
    QString                 m_startMarker;
    QString                 m_endMarker;
    QTimeLine               m_timeLine;
    QRecursiveMutex         m_mutex;
    QImage                  m_curImage;
    QSize                   m_defaultSize;
    QRecursiveMutex         m_mutexImage;
};

#endif // QTLOTTIEWIDGET_H
